home *** CD-ROM | disk | FTP | other *** search
- /* Style Implementation for Hypertext HTStyle.c
- ** ==================================
- **
- ** Styles allow the translation between a logical property
- ** of a piece of text and its physical representation.
- **
- ** A StyleSheet is a collection of styles, defining the
- ** translation necessary to
- ** represent a document. It is a linked list of styles.
- */
- #include"capalloc.h"
- #include"capstdio.h"
- #include "HTStyle.h"
- #include "HTUtils.h"
-
- /* Create a new style
- */
- PUBLIC HTStyle* HTStyleNew NOARGS
- {
- HTStyle * self = (HTStyle *)malloc(sizeof(*self));
- memset(self, 0, sizeof(*self));
- self->font = (HTFont) 0;
- self->color = 0;
- return self;
- }
-
- /* Create a new style with a name
- */
- PUBLIC HTStyle* HTStyleNewNamed ARGS1 (CONST char *,name)
- {
- HTStyle * self = HTStyleNew();
- StrAllocCopy(self->name, name);
- return self;
- }
-
-
- /* Free a style
- */
- PUBLIC HTStyle * HTStyleFree ARGS1 (HTStyle *,self)
- {
- if (self->name) free(self->name);
- if (self->SGMLTag) free(self->SGMLTag);
- free(self);
- return 0;
- }
-
-
- #ifdef SUPPRESS /* Only on the NeXT */
- /* Read a style from a stream (without its name)
- ** --------------------------
- **
- ** Reads a style with paragraph information from a stream.
- ** The style name is not read or written by these routines.
- */
- #define NONE_STRING "(None)"
- #define HTStream NXStream
-
- HTStyle * HTStyleRead (HTStyle * style, HTStream * stream)
- {
- char myTag[STYLE_NAME_LENGTH];
- char fontName[STYLE_NAME_LENGTH];
- NXTextStyle *p;
- int tab;
- int gotpara; /* flag: have we got a paragraph definition? */
-
- NXScanf(stream, "%s%s%f%d",
- myTag,
- fontName,
- &style->fontSize,
- &gotpara);
- if (gotpara) {
- if (!style->paragraph) {
- style->paragraph = malloc(sizeof(*(style->paragraph)));
- style->paragraph->tabs = 0;
- }
- p = style->paragraph;
- NXScanf(stream, "%f%f%f%f%hd%f%f%hd",
- &p->indent1st,
- &p->indent2nd,
- &p->lineHt,
- &p->descentLine,
- &p->alignment,
- &style->spaceBefore,
- &style->spaceAfter,
- &p->numTabs);
- if (p->tabs) free(p->tabs);
- p->tabs = malloc(p->numTabs * sizeof(p->tabs[0]));
- for (tab=0; tab < p->numTabs; tab++) {
- NXScanf(stream, "%hd%f",
- &p->tabs[tab].kind,
- &p->tabs[tab].x);
- }
- } else { /* No paragraph */
- if (style->paragraph) {
- free(style->paragraph);
- style->paragraph = 0;
- }
- } /* if no paragraph */
- StrAllocCopy(style->SGMLTag, myTag);
- if (strcmp(fontName, NONE_STRING)==0)
- style->font = 0;
- else
- style->font = [Font newFont:fontName size:style->fontSize];
- return 0;
-
- }
-
-
- /* Write a style to a stream in a compatible way
- */
- HTStyle * HTStyleWrite (HTStyle * style, NXStream * stream)
- {
- int tab;
- NXTextStyle *p = style->paragraph;
- NXPrintf(stream, "%s %s %f %d\n",
- style->SGMLTag,
- style->font ? [style->font name] : NONE_STRING,
- style->fontSize,
- p!=0);
-
- if (p) {
- NXPrintf(stream, "\t%f %f %f %f %d %f %f\t%d\n",
- p->indent1st,
- p->indent2nd,
- p->lineHt,
- p->descentLine,
- p->alignment,
- style->spaceBefore,
- style->spaceAfter,
- p->numTabs);
-
- for (tab=0; tab < p->numTabs; tab++)
- NXPrintf(stream, "\t%d %f\n",
- p->tabs[tab].kind,
- p->tabs[tab].x);
- }
- return style;
- }
-
-
- /* Write a style to stdout for diagnostics
- */
- HTStyle * HTStyleDump (HTStyle * style)
- {
- int tab;
- NXTextStyle *p = style->paragraph;
- printf("Style %d `%s' SGML:%s. Font %s %.1f point.\n",
- style,
- style->name,
- style->SGMLTag,
- [style->font name],
- style->fontSize);
- if (p) {
- printf(
- "\tIndents: first=%.0f others=%.0f, Height=%.1f Desc=%.1f\n"
- "\tAlign=%d, %d tabs. (%.0f before, %.0f after)\n",
- p->indent1st,
- p->indent2nd,
- p->lineHt,
- p->descentLine,
- p->alignment,
- p->numTabs,
- style->spaceBefore,
- style->spaceAfter);
-
- for (tab=0; tab < p->numTabs; tab++) {
- printf("\t\tTab kind=%d at %.0f\n",
- p->tabs[tab].kind,
- p->tabs[tab].x);
- }
- printf("\n");
- } /* if paragraph */
- return style;
- }
- #endif
-
-
- /* StyleSheet Functions
- ** ====================
- */
-
- /* Searching for styles:
- */
- HTStyle * HTStyleNamed ARGS2 (HTStyleSheet *,self, CONST char *,name)
- {
- HTStyle * scan;
- for (scan=self->styles; scan; scan=scan->next)
- if (0==strcmp(scan->name, name)) return scan;
- #ifndef RELEASE
- if (TRACE) fprintf(stderr, "StyleSheet: No style named `%s'\n", name);
- #endif /* RELEASE */
- return 0;
- }
-
- #ifdef NEXT_SUPRESS /* Not in general common code */
-
- HTStyle * HTStyleMatching (HTStyleSheet * self, HTStyle *style)
- {
- HTStyle * scan;
- for (scan=self->styles; scan; scan=scan->next)
- if (scan->paragraph == para) return scan;
- return 0;
- }
-
- /* Find the style which best fits a given run
- ** ------------------------------------------
- **
- ** This heuristic is used for guessing the style for a run of
- ** text which has been pasted in. In order, we try:
- **
- ** A style whose paragraph structure is actually used by the run.
- ** A style matching in font
- ** A style matching in paragraph style exactly
- ** A style matching in paragraph to a degree
- */
-
- HTStyle * HTStyleForRun (HTStyleSheet *self, NXRun *run)
- {
- HTStyle * scan;
- HTStyle * best = 0;
- int bestMatch = 0;
- NXTextStyle * rp = run->paraStyle;
- for (scan=self->styles; scan; scan=scan->next)
- if (scan->paragraph == run->paraStyle) return scan; /* Exact */
-
- for (scan=self->styles; scan; scan=scan->next){
- NXTextStyle * sp = scan->paragraph;
- if (sp) {
- int match = 0;
- if (sp->indent1st == rp->indent1st) match = match+1;
- if (sp->indent2nd == rp->indent2nd) match = match+2;
- if (sp->lineHt == rp->lineHt) match = match+1;
- if (sp->numTabs == rp->numTabs) match = match+1;
- if (sp->alignment == rp->alignment) match = match+3;
- if (scan->font == run->font) match = match+10;
- if (match>bestMatch) {
- best=scan;
- bestMatch=match;
- }
- }
- }
- #ifndef RELEASE
- if (TRACE) fprintf(stderr, "HTStyleForRun: Best match for style is %d out of 18\n",
- bestMatch);
- #endif /* RELEASE */
- return best;
- }
- #endif
-
-
- /* Add a style to a sheet
- ** ----------------------
- */
- HTStyleSheet * HTStyleSheetAddStyle ARGS2
- (HTStyleSheet *,self, HTStyle *,style)
- {
- style->next = 0; /* The style will go on the end */
- if (!self->styles) {
- self->styles = style;
- } else {
- HTStyle * scan;
- for(scan=self->styles; scan->next; scan=scan->next); /* Find end */
- scan->next=style;
- }
- return self;
- }
-
-
- /* Remove the given object from a style sheet if it exists
- */
- HTStyleSheet * HTStyleSheetRemoveStyle ARGS2
- (HTStyleSheet *,self, HTStyle *,style)
- {
- if (self->styles = style) {
- self->styles = style->next;
- return self;
- } else {
- HTStyle * scan;
- for(scan = self->styles; scan; scan = scan->next) {
- if (scan->next = style) {
- scan->next = style->next;
- return self;
- }
- }
- }
- return 0;
- }
-
- /* Create new style sheet
- */
-
- HTStyleSheet * HTStyleSheetNew NOARGS
- {
- HTStyleSheet * self = (HTStyleSheet *)malloc(sizeof(*self));
-
- memset((void*)self, 0, sizeof(*self)); /* ANSI */
- /* Harbison c ref man says (char*)self
- but k&r ansii and abc books and Think_C say (void*) */
-
- /* bzero(self, sizeof(*self)); */ /* BSD */
- return self;
- }
-
-
- /* Free off a style sheet pointer
- */
- HTStyleSheet * HTStyleSheetFree ARGS1 (HTStyleSheet *,self)
- {
- HTStyle * style;
- while((style=self->styles)!=0) {
- self->styles = style->next;
- HTStyleFree(style);
- }
- free(self);
- return 0;
- }
-
-
- /* Read a stylesheet from a typed stream
- ** -------------------------------------
- **
- ** Reads a style sheet from a stream. If new styles have the same names
- ** as existing styles, they replace the old ones without changing the ids.
- */
-
- #ifdef NEXT_SUPRESS /* Only on the NeXT */
- HTStyleSheet * HTStyleSheetRead(HTStyleSheet * self, NXStream * stream)
- {
- int numStyles;
- int i;
- HTStyle * style;
- char styleName[80];
- NXScanf(stream, " %d ", &numStyles);
- #ifndef RELEASE
- if (TRACE) fprintf(stderr, "Stylesheet: Reading %d styles\n", numStyles);
- #endif /* RELEASE */
- for (i=0; i<numStyles; i++) {
- NXScanf(stream, "%s", styleName);
- style = HTStyleNamed(self, styleName);
- if (!style) {
- style = HTStyleNewNamed(styleName);
- (void) HTStyleSheetAddStyle(self, style);
- }
- (void) HTStyleRead(style, stream);
- #ifndef RELEASE
- if (TRACE) HTStyleDump(style);
- #endif /* RELEASE */
- }
- return self;
- }
-
- /* Write a stylesheet to a typed stream
- ** ------------------------------------
- **
- ** Writes a style sheet to a stream.
- */
-
- HTStyleSheet * HTStyleSheetWrite(HTStyleSheet * self, NXStream * stream)
- {
- int numStyles = 0;
- HTStyle * style;
-
- for(style=self->styles; style; style=style->next) numStyles++;
- NXPrintf(stream, "%d\n", numStyles);
-
- #ifndef RELEASE
- if (TRACE) fprintf(stderr, "StyleSheet: Writing %d styles\n", numStyles);
- #endif /* RELEASE */
- for (style=self->styles; style; style=style->next) {
- NXPrintf(stream, "%s ", style->name);
- (void) HTStyleWrite(style, stream);
- }
- return self;
- }
- #endif
-